# -*- coding: utf-8 -*-
"""
Created on 2020/12/17

@author: zengjw5
"""

"""
功能：读取数据（publish端，提供了图像和音频的单条特征读取）
"""

import re
import pandas as pd
import logging
import os
from PIL import Image
import numpy as np
from app.utils.ResponseUtil import *
from pyAudioAnalysis import MidTermFeatures as aF
from pyAudioAnalysis import audioTrainTest as aT
from pyAudioAnalysis import audioBasicIO
from os import rename
import zipfile

logger = logging.getLogger(__name__)  # 返回一个新的以文件名为名的logger


class LoadData:
    """
    读取本地数据
    """

    @staticmethod
    def get_local_data(file, encoding=None, task_type=None, sep=None, sheet=None):
        data = None
        file_name_df = None

        ##定义解压zip文件函数
        # def unzip_file(zip_src, dst_dir):
        #     r = zipfile.is_zipfile(zip_src)
        #     if r:
        #         fz = zipfile.ZipFile(zip_src, 'r')
        #         for file in fz.namelist():
        #             fz.extract(file, dst_dir)
        #     else:
        #         print('This is not zip')
        def unzip_file(zip_src, dst_dir):   #修复解压乱码
            with zipfile.ZipFile(zip_src, 'r') as fd:
                for i in fd.namelist():
                    gbkfilename = i.encode('cp437').decode('GBK')
                    fd.extract(i, dst_dir)
                    rename(''.join([dst_dir + '/', i]), ''.join([dst_dir + '/', gbkfilename]))

        # 递归判断文件在第几层文件夹
        def fileCount(file_path, value, target_floor, cnt=1):

            data_listdir_name = os.listdir(file_path)
            old_cnt = cnt
            # 判断文件夹下是否有文件夹，然后循环
            for path in data_listdir_name:
                cnt = old_cnt
                if os.path.isdir(file_path + '/' + path):
                    newfile_path = file_path + '/' + path
                    value, cnt = fileCount(newfile_path, value, target_floor, cnt)

            cnt += 1
            ##查看第几层的文件夹
            if cnt == target_floor:
                value.append(file_path)
                return value, cnt
            else:
                return value, cnt

        try:
            if task_type in ['1001', '1002', '1003', '1004', '1005', '1006','sklearn']:
                if re.search('\.xlsx?$', file):
                    if sheet is not None:
                        data = pd.read_excel(file, sheet_name=sheet)
                    else:
                        data = pd.read_excel(file)
                elif re.search('\.csv$', file):
                    if sep is not None:
                        data = pd.read_csv(file, encoding=encoding, sep=sep)
                    else:
                        data = pd.read_csv(file, encoding=encoding)  # 默认为制表符\t
                elif re.search('\.txt$', file):
                    if sep is not None:
                        data = pd.read_table(file, encoding=encoding, sep=sep)
                    else:
                        data = pd.read_table(file, encoding=encoding)  #
            if task_type == '1007':  # 不同于训练端，这里读取进来是不带有target的，且可通过判断后缀来读取单条（单图像/音频文件）
                def Load_IMAGE_Data(file_path='./dataset_MNIST/test'):
                    file_img_list = os.listdir(file_path)  # label文件夹list
                    data_img_list = []
                    for j in file_img_list:  # 文件夹下输入，每个label都输入
                        img_path = file_path + '/' + j
                        width_max, height_max = 126, 126
                        data_img_list.append(np.asarray(Image.open(img_path).resize((width_max, height_max), Image.BILINEAR)))
                    data = pd.DataFrame()
                    data['img_array'] = data_img_list
                    file_name_df = pd.DataFrame(file_img_list, columns=['file_name'])
                    return data, file_name_df

                if re.search('\.zip$', file):  # 判别是否为zip结尾
                    file_zip = file
                    file = file_zip[:-4]
                    unzip_file(file_zip, file)  # 解压文件

                    # 选择第二层文件
                    value = []
                    file_path = fileCount(file, value, 2)[0][0]

                    data, file_name_df = Load_IMAGE_Data(file_path=file_path)  # 图片矩阵df

                elif re.search('\.png$', file):  # png文件才读取,单条读取
                    data_img_list = []
                    width_max, height_max = 126, 126
                    data_img_list.append(np.asarray(Image.open(file).resize((width_max, height_max), Image.BILINEAR)))
                    data = pd.DataFrame()
                    data['img_array'] = data_img_list
                    file_name_df = pd.DataFrame([file.split('/')[-1]], columns=['file_name'])

            if task_type == '1008':
                ##读入文件夹下音频文件的特征，并将features转为df格式
                def extract_audio_feature(folder_path, mid_window, mid_step, short_window, short_step,
                                          compute_beat=False):
                    sampling_rate, signal = audioBasicIO.read_audio_file(folder_path)
                    signal = audioBasicIO.stereo_to_mono(signal)
                    if compute_beat:
                        mid_features, short_features, mid_feature_names = \
                            aF.mid_feature_extraction(signal, sampling_rate,
                                                      round(mid_window * sampling_rate),
                                                      round(mid_step * sampling_rate),
                                                      round(sampling_rate * short_window),
                                                      round(sampling_rate * short_step))
                        beat, beat_conf = aF.beat_extraction(short_features, short_step)
                    else:
                        mid_features, _, mid_feature_names = \
                            aF.mid_feature_extraction(signal, sampling_rate,
                                                      round(mid_window * sampling_rate),
                                                      round(mid_step * sampling_rate),
                                                      round(sampling_rate * short_window),
                                                      round(sampling_rate * short_step))

                    mid_features = np.transpose(mid_features)
                    mid_features = mid_features.mean(axis=0)
                    # long term averaging of mid-term statistics
                    if (not np.isnan(mid_features).any()) and \
                            (not np.isinf(mid_features).any()):
                        if compute_beat:
                            mid_features = np.append(mid_features, beat)
                            mid_features = np.append(mid_features, beat_conf)
                    return mid_features, folder_path, mid_feature_names

                if re.search('\.zip$', file):  # 判别是否为zip结尾
                    file_zip = file
                    file = file_zip[:-4]
                    unzip_file(file_zip, file)  # 解压文件

                    # 选择第二层文件
                    value = []
                    file_path = fileCount(file, value, 2)[0][0]
                    label_path_list = []
                    for i in os.listdir(file_path):
                        label_path_list.append(file_path + '/' + i)

                    features = []
                    names = []
                    for j in label_path_list:

                        # file = file + '/' + os.listdir(file)[0]
                        feature, name, _ = extract_audio_feature(j, 1.0, 1.0,
                                                                             aT.shortTermWindow,
                                                                             aT.shortTermStep,
                                                                             compute_beat=False)
                        features.append(feature)
                        names.append(name)

                    colunm_list =[]
                    for i in range(len(features[0])):
                        colunm_list.append(str(i))

                    data = pd.DataFrame(features,columns=colunm_list)
                    logging.info(data)
                    file_name_list = []
                    for i in names:
                        file_name_list.append(i.split('/')[-1])
                    file_name_df = pd.DataFrame(file_name_list, columns=['file_name'])
                elif re.search('\.wav$', file):  # wav文件才读取
                    feature, name, _ = extract_audio_feature(file, 1.0, 1.0, aT.shortTermWindow, aT.shortTermStep,
                                                             compute_beat=False)
                    file_name_df = pd.DataFrame([name.split('/')[-1]], columns=['file_name'])
                    data = pd.DataFrame([feature])

            if task_type in ('1009','1010'):
                if re.search('\.zip$', file):  # 判别是否为zip结尾
                    file_zip = file
                    file = file_zip[:-4]
                    unzip_file(file_zip, file)  # 解压文件

                    # 选择第二层文件
                    value = []
                    file_path = fileCount(file, value, 2)[0][0]
                    image_list = []
                    file_img_list = os.listdir(file_path)  # label文件夹list
                    for j in file_img_list:  # 文件夹下输入，每个label都输入
                        image_list.append(file_path + '/' + j)
                    data = pd.DataFrame(image_list,columns=['image_path'])

            if task_type == 'matlab':
                if re.search('\.zip$', file):  # 判别是否为zip结尾
                    file_zip = file
                    file = file_zip[:-4]
                    unzip_file(file_zip, file)  # 解压文件

                    # 选择第二层文件
                    value = []
                    file_path = fileCount(file, value, 2)[0][0]
                    image_list = []
                    file_img_list = os.listdir(file_path)  # label文件夹list
                    if file_img_list is not None and len(file_img_list) == 2:
                        for j in file_img_list:  # 文件夹下输入，每个label都输入
                            if re.search('\.m$', j):
                                data = file_path + '/' + j
                            else:
                                file_name_df = file_path + '/' + j



        except Exception as e:
            logging.error(ResponseMessage.ReadResourceFail + ':' + str(e), exc_info=True)  # 读取本地数据失败
            error_code_msg = ResponseCode.ReadResourceFail + ':' + ResponseMessage.ReadResourceFail
            raise Exception(error_code_msg)
        return data, file_name_df




